<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <!-- <script src="./util.js"></script>
  <script src="./background.js"></script>
  <script src="./game.js"></script> -->
  <style>
    html,
    body,
    #container {
      height: 100%;
      width: 100%;
    }

    #container {
      display: flex;
      justify-content: center;
      align-items: center;
    }

    #canvas {
      display: block;
      /* background: red; */
    }
  </style>
</head>

<body>
  <div id="container">
    <canvas id="canvas" width="360" height="540"></canvas>
  </div>
  <script>
    // 基础数据准备
    var canvas = document.getElementById('canvas')
    var ctx = canvas.getContext('2d')
    var score = 0
    var gameOver = false
    /** 
     * 绘制图像元素
     */
    function drawImage(option) {
      // 参数校验
      if (!option.image || !(option.image instanceof Image)) {
        console.error('请传入有效的image')
        return
      }

      // 生成默认配置
      // 需要在image状态为complete时生成
      var generateOption = function () {
        // 默认配置
        var defaultOption = {
          x: 0, // 绘制位置x坐标
          y: 0, // 绘制位置y坐标
          width: option.image.width,
          height: option.image.height,
          sx: 0,  // 裁剪位置x坐标
          sy: 0, // 裁剪位置y坐标
          swidth: option.image.width,
          sheight: option.image.height
        }
        return Object.assign({}, defaultOption, option)
      }

      // 绘制图像
      var draw = function () {
        ctx.drawImage(option.image, option.sx, option.sy, option.swidth, option.sheight, option.x, option.y, option.width, option.height);
      }

      // 用于初始初始绘制
      // 生成配置文件
      var init = function () {
        option = generateOption()
        draw(option)
      }

      // 图像加载完成时绘制
      if (option.image.complete) {
        init()
      } else {
        option.image.onload = init
      }
    }

    /**
     * 背景绘制类
     * 主要用于绘制天空以及地面背景
     */
    function Background(x, y, width, height, imgSrc, update) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
      this.image = new Image()
      this.image.src = imgSrc
      var self = this
      // 添加重绘方法
      this.draw = function () {
        drawImage({
          x: this.x,
          y: this.y,
          width: this.width,
          height: this.height,
          image: this.image
        })
      }

      // 支持更新扩展
      if (update) {
        this.update = update
      }
    }

    function Bird(x, y, width, height, imgSrc, speed) {
      this.x = x
      this.y = y
      this.width = width
      this.height = height
      this.index = 0
      this.speed = speed
      this.image = new Image()
      this.image.src = imgSrc
      var self = this

      this.update = function () {
        this.index++
        this.speed = this.speed + (this.index / 300)
        this.y = this.y + this.speed
      }

      this.check = function (pipes, ground) {
        // 管道碰撞检测
        for (var index in pipes) {
          var pipe = pipes[index]
          if (
            (this.x + this.width) > pipe.x &&
            this.x < (pipe.x + pipe.width) &&
            (
              this.y < (pipe.height - pipe.offset) ||
              this.y > (pipe.height - pipe.offset + pipe.spaceHeight)
            )
          ) {
            gameOver = true
          }
        }

        // 地面碰撞检测
        if ((this.y + this.height) > ground.y) {
          gameOver = true
        }
      }

      this.draw = function () {
        drawImage({
          x: this.x,
          y: this.y,
          sx: 675,
          sy: 60 * (Math.floor(this.index / 5) % 3),   // 5表示降低翅膀煽动频率
          swidth: 80,
          sheight: 60,
          width: this.width,
          height: this.height,
          image: this.image
        })
      }
    }

    function Pipe(x, y, width, height, imageSrc, speed) {
      this.x = x
      this.offset = 200 - ((Math.random() > 0.5 ? 1 : -1) * Math.random() * 150)
      this.y = y - this.offset// 100是保证通道在中间的偏移量
      this.width = width
      this.height = height
      this.image = new Image
      this.image.src = imageSrc
      this.spaceHeight = 150
      this.score = false

      // 更新
      this.update = function (bird) {
        // console.log(this.offset)
        if (!this.score && (this.x + this.width) < bird.x) {
          score += 1
          this.score = true
        }

        if (this.x < -(this.width)) {
          this.x = 360 + 300
          this.score = false
        }
        this.x -= speed || 2
      }

      this.draw = function () {
        // 绘制上层pipe
        drawImage({
          x: this.x,
          y: this.y,
          sx: 150,
          sy: 480,
          swidth: 140,
          sheight: 820,
          width: this.width,
          height: this.height,
          image: this.image
        })

        // 绘制下层pipe
        drawImage({
          x: this.x,
          y: this.y + this.height + this.spaceHeight,
          sx: 0,
          sy: 480,
          swidth: 140,
          sheight: 820,
          width: this.width,
          height: this.height,
          image: this.image
        })
      }
    }

    function Game() {
      this.init = function () {
        console.log(123)
      }
    }

    function addControl() {
      document.onkeyup = function () {
        if(gameOver){
            return
        }

        var e = e || event;
        var currKey = e.keyCode || e.which || e.charCode;

        switch (currKey) {
          case 32:
            bird.speed = -2.5
            bird.index = 0;
            break;
        }
      }
    }

    // 实例化背景对象
    var back = new Background(0, 0, 360, 540, "./bg.png");

    // 实例化地面对象
    var ground = new Background(0, 500, 500, 100, "./ground.png", function () {
      // 每个页面显示10个图片块
      // 每个图片块宽度54px
      // 按照图片块宽度的倍数进行切换可以实现无缝的滚动效果
      this.x = this.x < -(54 * 2) ? 0 : this.x - 1
    });

    // 实例化bird对象
    var bird = new Bird(160, 240, 40, 30, './pipe.png', 2)

    var pipes = []

    for (var i = 0; i < 3; i++) {
      pipes.push(new Pipe(360 + i * 250, 0, 100, 400, './pipe.png'))
    }

    function drawScore() {
      ctx.fillStyle = "red";
      ctx.font = "40px Arial";
      ctx.fillText(score, 170, 90);
    }

    // var pipe = new Pipe(360, 0, 100, 300, './pipe.png')
    // 开启动画循环
    var loop = function () {
      if(gameOver){
        setTimeout(function(){
          cancelAnimationFrame(loopId);
        },1000)
        return 
      }

      var loopId = requestAnimationFrame(function () {
        ctx.clearRect(0, 0, 360, 540);
        back.draw()


        for (var i = 0, max = pipes.length; i < max; i++) {
          pipes[i].update(bird)
          pipes[i].draw()
        }

        bird.update()
        bird.draw()
        
        ground.update()
        ground.draw()
        bird.check(pipes, ground)
        drawScore()
        loop()
      })
    }

    loop()

    addControl()

  </script>

</body>

</html>